package compro.admission.form.service;

import javax.annotation.Resource;

import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import compro.admission.form.dao.ApplicationDAO;
import compro.admission.form.dao.UserDAO;
import compro.admission.form.email.NotifyApplicationEmail;
import compro.admission.form.email.RequestResetApplicationEmail;
import compro.admission.form.email.ResetApproveEmail;
import compro.admission.form.email.ResetRejectEmail;
import compro.admission.form.email.SubmitApplicationEmail;
import compro.admission.form.entity.Application;
import compro.admission.form.entity.Education;
import compro.admission.form.entity.EnglishProficiency;
import compro.admission.form.entity.PersonalInformaion;
import compro.admission.form.entity.Prerequisites;
import compro.admission.form.entity.ProfessionalExperience;
import compro.admission.form.entity.SelfStudy;
import compro.admission.form.entity.User;
import compro.admission.form.entity.ProgrammingSkill;
import compro.admission.form.evaluation.Evaluation;
import compro.admission.form.evaluation.Evaluation.resultType;

@Component
@Transactional(propagation = Propagation.REQUIRED)
public class ApplicationService {
	private ApplicationDAO applicationDAO;
	private UserDAO userDAO;

	public ApplicationDAO getApplicationDAO() {
		return applicationDAO;
	}

	@Resource
	public void setApplicationDAO(ApplicationDAO applicationDAO) {
		this.applicationDAO = applicationDAO;
	}

	public UserDAO getUserDAO() {
		return userDAO;
	}

	@Resource
	public void setUserDAO(UserDAO userDAO) {
		this.userDAO = userDAO;
	}
	/*-------------------------------------------------------------------
	 0. Application
	 -------------------------------------------------------------------*/
	public void saveApplication(Application application) {
		this.applicationDAO.saveApplication(application);
	}

	public Application getApplicationByUser(User user) {
		Application application = this.applicationDAO.getApplication(user);
		return application;
	}

	public Application getApplicationById(long id) {
		return applicationDAO.getApplicationById(id);
		
	}

	public Application createApplication(User user) {
		User originalUser = userDAO.getUserByEmail(user.getEmail());
		Application application = new Application(originalUser);
		this.applicationDAO.saveApplication(application);
		return application;
	}

	public void resetApplication(Boolean isApprove, Application application) {
		if (isApprove) {
			application.setDisposition("unsubmitted");
			this.applicationDAO.updateApplication(application);
		}
		generateEmail(isApprove, application);
	}

	public void generateEmail(Boolean isApprove, Application application) {
		User user = application.getUser();
		if (isApprove) {
			ResetApproveEmail approveEmail = new ResetApproveEmail(user,
					application);
			approveEmail.sendEmail();
		} else {
			ResetRejectEmail rejectEmail = new ResetRejectEmail(user,
					application);
			rejectEmail.sendEmail();
		}
	}

	public void passFailApplication(Application application, boolean isPass) {
		if (isPass)
			application.setDisposition("passed");
		else
			application.setDisposition("failed");

		applicationDAO.updateApplication(application);
		User admin = userDAO.getUserAdmission();
		SubmitApplicationEmail email = new SubmitApplicationEmail(admin,
				application);
		email.sendEmail();

		NotifyApplicationEmail notify = new NotifyApplicationEmail(
				application.getUser(), application);
		notify.sendEmail();

	}

	public void submitApplication(Application application) {
		Evaluation evaluation = new Evaluation(application);
		Evaluation.resultType result = evaluation.Evaluate();
		if (result == resultType.FAIL)
			application.setDisposition("failed");
		else if (result == resultType.PASS)
			application.setDisposition("passed");
		else
			application.setDisposition("undetermined");
		applicationDAO.updateApplication(application);
		User admin = userDAO.getUserAdmission();
		SubmitApplicationEmail email = new SubmitApplicationEmail(admin,
				application);
		email.sendEmail();

		NotifyApplicationEmail notify = new NotifyApplicationEmail(
				application.getUser(), application);
		notify.sendEmail();

	}

	public void requestResetApplication(Application application) {
		applicationDAO.updateApplication(application);
		User user = userDAO.getUserAdmission();
		RequestResetApplicationEmail requestEmail = new RequestResetApplicationEmail(
				user, application);
		requestEmail.sendEmail();
	}

	/*-------------------------------------------------------------------
	 1. Personal Information
	 -------------------------------------------------------------------*/
	public PersonalInformaion getPersonalInformation(Application application) {
		return applicationDAO.getPersonalInformation(application);
	}

	public void savePersonalInformaion(PersonalInformaion personalInformaion,
			Application application) {
		Application originalApplication = getApplicationById(application
				.getId());
		PersonalInformaion oldPersonalInformaion = applicationDAO
				.getPersonalInformation(originalApplication);
		if (oldPersonalInformaion == null) {
			personalInformaion.setApplication(originalApplication);
			originalApplication.setPersonalInformaion(personalInformaion);
			applicationDAO.savePersonalInformaion(personalInformaion);
		} else {
			int id = oldPersonalInformaion.getId();
			BeanUtils.copyProperties(personalInformaion, oldPersonalInformaion);
			oldPersonalInformaion.setId(id);
			applicationDAO.updatePersonalInformation(oldPersonalInformaion);
		}

	}

	/*-------------------------------------------------------------------
	 2. English Proficiency
	 -------------------------------------------------------------------*/
	public EnglishProficiency getEnglishProficiency(Application application) {
		return applicationDAO.getEnglishProficiency(application);
	}

	public void saveEnglishProficiency(EnglishProficiency englishProficiency,
			Application application) {
		Application originalApplication = getApplicationById(application
				.getId());
		EnglishProficiency oldEnglishProficiency = applicationDAO
				.getEnglishProficiency(originalApplication);
		if (oldEnglishProficiency == null) {
			englishProficiency.setApplication(originalApplication);
			originalApplication.setEnglishProficiency(englishProficiency);
			applicationDAO.saveEnglishProficiency(englishProficiency);
		} else {
			int id = oldEnglishProficiency.getId();
			BeanUtils.copyProperties(englishProficiency, oldEnglishProficiency);
			oldEnglishProficiency.setId(id);
			applicationDAO.updateEnglishProficiency(oldEnglishProficiency);
		}
	}

	/*-------------------------------------------------------------------
	 3. Education History
	 -------------------------------------------------------------------*/
	public Education getEducation(Application application) {
		return applicationDAO.getEducation(application);
	}

	public void saveEducation(Education education, Application application) {
		Application originalApplication = getApplicationById(application
				.getId());
		Education oldEducation = applicationDAO
				.getEducation(originalApplication);
		if (oldEducation == null) {
			education.setApplication(originalApplication);
			originalApplication.setEducation(education);
			applicationDAO.saveEducation(education);
		} else {
			int id = oldEducation.getId();
			BeanUtils.copyProperties(education, oldEducation);
			oldEducation.setId(id);
			applicationDAO.updateEducation(oldEducation);
		}
	}

	/*-------------------------------------------------------------------
	 4. Programming Skill
	 -------------------------------------------------------------------*/
	public ProgrammingSkill getProgrammingSkill(Application application) {
		return applicationDAO.getProgrammingSkill(application);
	}

	public void saveProgrammingSkill(ProgrammingSkill programmingSkill,
			Application application) {
		Application originalApplication = getApplicationById(application
				.getId());
		ProgrammingSkill oldProgrammingSkill = applicationDAO
				.getProgrammingSkill(originalApplication);
		if (oldProgrammingSkill == null) {
			programmingSkill.setApplication(originalApplication);
			originalApplication.setProgrammingSkill(programmingSkill);
			applicationDAO.saveProgrammingSkill(programmingSkill);
		} else {
			int id = oldProgrammingSkill.getId();
			BeanUtils.copyProperties(programmingSkill, oldProgrammingSkill);
			oldProgrammingSkill.setId(id);
			applicationDAO.updateProgrammingSkill(oldProgrammingSkill);
		}

	}

	/*-------------------------------------------------------------------
	 5. Prerequisite
	 -------------------------------------------------------------------*/

	/*-------------------------------------------------------------------
	 6. Professional Experience
	 -------------------------------------------------------------------*/
	public ProfessionalExperience getProfessionalExperience(
			Application application) {
		return applicationDAO.getProfessionalExperience(application);
	}

	public void saveProfessionalExperience(
			ProfessionalExperience professionalExperience,
			Application application) {
		Application originalApplication = getApplicationById(application
				.getId());
		ProfessionalExperience oldProfessionalExperience = applicationDAO
				.getProfessionalExperience(originalApplication);
		if (oldProfessionalExperience == null) {
			professionalExperience.setApplication(originalApplication);
			originalApplication
					.setProfessionalExperience(professionalExperience);
			applicationDAO.saveProfessionalExperience(professionalExperience);
		} else {
			int professionalExperienceId = oldProfessionalExperience.getId();
			BeanUtils.copyProperties(professionalExperience,
					oldProfessionalExperience);
			oldProfessionalExperience.setId(professionalExperienceId);
			applicationDAO.updatePersonalInformation(oldProfessionalExperience);
		}
	}

	/*-------------------------------------------------------------------
	 7. Self Study
	 -------------------------------------------------------------------*/
	public void saveSelfStudy(SelfStudy selfStudy, Application application) {
		Application originalApplication = getApplicationById(application
				.getId());
		SelfStudy oldSelfStudy = applicationDAO
				.getSelfStudy(originalApplication);
		if (oldSelfStudy == null) {
			selfStudy.setApplication(originalApplication);
			originalApplication.setSelfStudy(selfStudy);
			applicationDAO.saveSelfStudy(selfStudy);
		} else {
			int selfStudyId = oldSelfStudy.getId();
			BeanUtils.copyProperties(selfStudy, oldSelfStudy);
			oldSelfStudy.setId(selfStudyId);
			applicationDAO.updateSelfStudy(oldSelfStudy);
		}
	}

	public SelfStudy getSelfStudy(Application application) {
		return applicationDAO.getSelfStudy(application);
	}

	public void savePrerequisite(Prerequisites prerequisites,
			Application application) {
		Application originalApplication = getApplicationById(application
				.getId());
		Prerequisites oldPrerequisites = applicationDAO
				.getPrerequisites(originalApplication);
		if (oldPrerequisites == null) {
			prerequisites.setApplication(originalApplication);
			originalApplication.setPrerequisites(prerequisites);
			applicationDAO.savePrerequisites(prerequisites);
		} else {
			long prerequisitesId = oldPrerequisites.getId();
			BeanUtils.copyProperties(prerequisites, oldPrerequisites);
			oldPrerequisites.setId(prerequisitesId);
			applicationDAO.updateSelfStudy(oldPrerequisites);
		}
	}

	public Prerequisites getPrerequisites(Application application) {
		return applicationDAO.getPrerequisites(application);
	}
}
